package com.pucong.gitee.database.backup.utils;

import com.pucong.gitee.database.backup.common.selfenum.CommonEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


/**
 * 枚举类处理类
 * @author pucong
 * @url https://gitee.com/pucong
 * @create 2020-06-10
 */
public class EnumTypeHandler <E extends Enum<E>>  extends BaseTypeHandler<CommonEnum>{

	private Logger logger = LoggerFactory.getLogger(EnumTypeHandler.class);

    private Class<CommonEnum> type;

    private final CommonEnum[] enums;

    /**
     * 设置配置文件设置的转换类以及枚举类内容，供其他方法更便捷高效的实现
     * @param type 配置文件中设置的转换类
     */
    public EnumTypeHandler(Class<CommonEnum> type) {
        if (type == null){
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
        this.enums = type.getEnumConstants();
        if (this.enums == null){
            throw new IllegalArgumentException(type.getSimpleName()
                    + " does not represent an enum type.");
        }
    }

	@Override
	public CommonEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放Sting类型
        String i = rs.getString(columnName);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值，定位EnumStatus子类
            return locateEnumStatus(i);
        }
	}

	@Override
	public CommonEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放Sting类型
        logger.debug(columnIndex+"");
        String i = rs.getString(columnIndex);
        if (rs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值，定位EnumStatus子类
            return locateEnumStatus(i);
        }
	}

	@Override
	public CommonEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
		// 根据数据库存储类型决定获取类型，本例子中数据库中存放Sting类型
        logger.debug(columnIndex+"");
        String i = cs.getString(columnIndex);
        if (cs.wasNull()) {
            return null;
        } else {
            // 根据数据库中的code值，定位EnumStatus子类
            return locateEnumStatus(i);
        }
	}

	@Override
	public void setNonNullParameter(PreparedStatement ps, int i, CommonEnum parameter, JdbcType arg3)
			throws SQLException {
		// baseTypeHandler已经帮我们做了parameter的null判断
        logger.debug(parameter.getValue().toString()+"=================================");
        ps.setString(i, parameter.getValue().toString());
	}

	/**
     * 枚举类型转换，由于构造函数获取了枚举的子类enums，让遍历更加高效快捷
     * @param code 数据库中存储的自定义code属性
     * @return code对应的枚举类
     */
    private CommonEnum locateEnumStatus(String code) {
        for(CommonEnum status : enums) {
            if(code .equals(status.getValue().toString())) {
                return status;
            }
        }
        throw new IllegalArgumentException("未知的枚举类型：" + code + ",请核对" + type.getSimpleName());
    }
}